package anno.ioc;


import anno.Autowired;
import anno.Component;

import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class BeanFactory {
    // 单例实例
    private static final BeanFactory INSTANCE = new BeanFactory();

    private final Map<Class<?>, Object> beans = new ConcurrentHashMap<>();

    // 私有构造函数
    public BeanFactory() {}

    // 获取BeanFactory实例
    public static BeanFactory getInstance() {
        return INSTANCE;
    }

    // 静态初始化方法
    public static void initBeans(String basePackage) {
        INSTANCE.scan(basePackage);
        INSTANCE.inject();
    }

    // 静态获取Bean方法
    public static <T> T getBean(Class<T> type) {
        return INSTANCE.getBeanInstance(type);
    }

    // 实际的获取Bean实例的方法
    private <T> T getBeanInstance(Class<T> type) {
        Object bean = beans.get(type);
        if (bean == null) {
            System.err.println("警告: 找不到类型为 " + type.getName() + " 的Bean");
            return null;
        }
        return type.cast(bean);
    }

    public void scan(String basePackage) {
        try {
            System.out.println("开始扫描包: " + (basePackage.isEmpty() ? "根目录" : basePackage));

            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            String path = basePackage.replace('.', '/');
            URL url = classLoader.getResource("");  // 获取类路径根目录

            if (url != null) {
                System.out.println("类路径根目录: " + url.getPath());
                File root = new File(url.getFile());
                scanDirectory(root, "");
            } else {
                System.err.println("无法获取类路径根目录");
            }

            // 打印所有找到的bean
            System.out.println("\n已注册的Bean列表:");
            beans.forEach((key, value) ->
                    System.out.println(" - " + key.getName() + " => " + value.getClass().getName()));

        } catch (Exception e) {
            System.err.println("扫描包失败: " + e.getMessage());
            e.printStackTrace();
            throw new RuntimeException("扫描包失败", e);
        }
    }

    private void scanDirectory(File directory, String packageName) {
//        System.out.println("扫描目录: " + directory.getAbsolutePath());

        File[] files = directory.listFiles();
        if (files != null) {
            for (File file : files) {
                String currentPackage = packageName.isEmpty() ?
                        file.getName() : packageName + "." + file.getName();

                if (file.isDirectory()) {
                    scanDirectory(file, currentPackage);
                } else if (file.getName().endsWith(".class")) {
                    String className = currentPackage.substring(0,
                            currentPackage.length() - 6);  // 去掉.class后缀
                    processClass(className);
                }
            }
        }
    }

    private void processClass(String className) {
        try {
            System.out.println("处理类: " + className);
            Class<?> clazz = Class.forName(className);

            if (clazz.isAnnotationPresent(Component.class)) {
                System.out.println("发现标注@Component的类: " + className);
                Object instance = clazz.getDeclaredConstructor().newInstance();
                beans.put(clazz, instance);
                System.out.println("成功创建Bean实例: " + className);

                // 注册接口
                for (Class<?> iface : clazz.getInterfaces()) {
                    if (!beans.containsKey(iface)) {
                        beans.put(iface, instance);
                        System.out.println("注册接口: " + iface.getName() + " => " + className);
                    }
                }
            }
        } catch (Exception e) {
            System.err.println("处理类失败: " + className);
            e.printStackTrace();
        }
    }

    public void inject() {
        System.out.println("\n开始注入依赖...");
        beans.forEach((type, bean) -> {
            System.out.println("\n处理Bean的依赖注入: " + type.getName());
            injectBean(bean);
        });
        System.out.println("\n依赖注入完成.");
    }

    private void injectBean(Object bean) {
        Class<?> beanClass = bean.getClass();
        for (Field field : beanClass.getDeclaredFields()) {
            if (field.isAnnotationPresent(Autowired.class)) {
                field.setAccessible(true);
                Class<?> fieldType = field.getType();
                Object dependency = beans.get(fieldType);

                if (dependency == null) {
                    System.err.println("警告: 找不到类型为 " + fieldType.getName() +
                            " 的Bean，该类型被 " + beanClass.getName() + " 所依赖");
                } else {
                    try {
                        field.set(bean, dependency);
                        System.out.println("成功注入依赖: " + beanClass.getName() +
                                " => " + fieldType.getName());
                    } catch (Exception e) {
                        System.err.println("注入依赖失败: " + e.getMessage());
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    // 静态清理方法
    public static void clearBeans() {
        System.out.println("清理所有Bean...");
        INSTANCE.beans.clear();
    }
}